#ifndef TIANYU_COMMON_GAME_OBJECT_MANAGER_H_
#define TIANYU_COMMON_GAME_OBJECT_MANAGER_H_

#include "object_pool.h"
#include "user_define.h"

#define OBJ_POOL_DEFINE( type, n, name, obj )						\
		obj.Initialize( n );										\
		pool_interface_[ type ].pool_interface_ = &obj;				\
		strncpy( pool_interface_[ type ].pool_obj_name_, name, sizeof( pool_interface_[ type ].pool_obj_name_ ) );

namespace common
{

	struct SPoolStruct
	{
		::common::CPoolInterface* pool_interface_;
		char pool_obj_name_[ 64 ];

		SPoolStruct( )
		{
			clear( );
		}

		void clear( )
		{
			memset( pool_obj_name_, 0, sizeof( pool_obj_name_ ) );
			pool_interface_ = NULL;
		}
	};

	template<int32_t pool_count>
	class CGameObjectManager
	{
	public:

		CGameObjectManager( )
		{
			for ( int32_t i = 0; i < pool_count; ++i )
			{
				pool_interface_[ i ].clear( );
			}
		}

		virtual ~CGameObjectManager( )
		{
		}

		virtual bool Initialize( ) = 0;

		virtual bool Finalize( )
		{
			for( unsigned int i = 0; i < ARRAY_CNT( pool_interface_ ); ++i )
			{
				if( pool_interface_[ i ].pool_interface_ != NULL )
				{
					pool_interface_[ i ].pool_interface_->Finalize( );
				}
			}
			return true;
		}

		template<typename T>
		T* CreateObject( int32_t obj_type )
		{
			if ( obj_type < 0 || obj_type >= pool_count )
			{
				return NULL;
			}
			::common::CPoolInterface* interfacea = pool_interface_[ obj_type ].pool_interface_;
			if ( NULL == interfacea )
			{
				return NULL;
			}
			T* t = dynamic_cast< T* >( interfacea->CreateObject( ) );
			LOG_DEBUG("default", "CreateObject %d, type %d, capacity %d size %d", ( t == NULL ) ? 0 : t->get_id( ), obj_type, 
				interfacea->capacity( ), interfacea->size( ) );
			return t;
		}

		template<typename T>
		T* GetObjectByID( OBJ_ID_TYPE id )
		{
			int32_t obj_type = CObj::ID2TYPE( id );
			if ( obj_type < 0 || obj_type >= pool_count )
			{
				return NULL;
			}
			::common::CPoolInterface* interfacea = pool_interface_[ obj_type ].pool_interface_;
			if ( NULL == interfacea )
			{
				return NULL;
			}
			return dynamic_cast< T* >( interfacea->GetObject4ID( id ) );
		}

		bool DestoryObject( OBJ_ID_TYPE id )
		{
			int32_t obj_type = CObj::ID2TYPE( id );
			if ( obj_type < 0 || obj_type >= pool_count )
			{
				return false;
			}
			::common::CPoolInterface* interfacea = pool_interface_[ obj_type ].pool_interface_;
			if ( NULL == interfacea )
			{
				return false;
			}
			interfacea->DestoryObject( id );
			//LOG_DEBUG("default","DestroyObject %d, type %d, capacity %d size %d", id, obj_type, interfacea->capacity( ), interfacea->size( ) );
			return true;
		}

		void Dump( char* buff, size_t& buff_len ) 
		{
			int use_len = 0;
			int max_len = buff_len;

			use_len += snprintf( buff + use_len, max_len - use_len, "\n%20s\t%6s\t%6s\n", "Name", "Free",
					"Total" );

			for( unsigned int i = 0; i < ARRAY_CNT( pool_interface_ ); ++i )
			{
				if( pool_interface_[ i ].pool_interface_ != NULL )
				{
					use_len += snprintf( buff + use_len, max_len - use_len, "%20s\t%6d\t%6d\n",
							pool_interface_[ i ].pool_obj_name_,
							pool_interface_[ i ].pool_interface_->size( ),
							pool_interface_[ i ].pool_interface_->capacity( ) );
				}
			}

			buff_len = max_len - use_len;	
		}

		void ObjManagerLoop( int32_t obj_type, common::ObjFunc fun, void* param )
		{
			if( obj_type < 0 || obj_type >= pool_count )
			{
				return;	
			}
			if( pool_interface_[ obj_type ].pool_interface_ != NULL )
			{
				pool_interface_[ obj_type ].pool_interface_->LoopFunc( fun, param );
			}	
		}
		
		int32_t GetMemberSize( int32_t obj_type )
		{
			if( obj_type < 0 || obj_type >= pool_count )
			{
				return 0;
			}
			return pool_interface_[ obj_type ].pool_interface_ == NULL ? 0 :  pool_interface_[ obj_type ].pool_interface_->size( );
		}

		int32_t GetEmptySize( int32_t obj_type )
		{
			if( obj_type < 0 || obj_type >= pool_count )
			{
				return 0;
			}
			return pool_interface_[ obj_type ].pool_interface_ == NULL ? 0 : pool_interface_[ obj_type ].pool_interface_->size( );
		}

	protected:
		SPoolStruct pool_interface_[ pool_count ];
	};

};//namespace common

#endif
